"""
time: 2025
author: CodeKpy & 小宏XeLa & 小树林 & Coconut Studio
"""
import base64
import json
import shutil

from flask import Flask, render_template, request, jsonify, make_response
import pipList
import subprocess
import os
import sys

# 默认环境
venv_path = "./project"

# TODO: 实现环境切换
# 获取当前程序的路径
if getattr(sys, 'frozen', False):
    # 打包后的可执行文件路径
    current_executable_path = sys.executable
else:
    # 普通脚本文件路径
    current_executable_path = os.path.abspath(__file__)

print(f"当前程序的路径: {current_executable_path}")
current_executable_dir = os.path.dirname(current_executable_path)
print(f"当前程序所在的目录: {current_executable_dir}")
print("访问网址：", "http://127.0.0.1:5000/")

# 获取./project的绝对路径
# 起始目录
base_dir = current_executable_dir
# 相对路径
relative_path = venv_path
# 获取绝对路径
absolute_path = os.path.abspath(os.path.join(base_dir, relative_path))

app = Flask(__name__, template_folder='./', static_folder='./')

# 判断是否存在project虚拟环境，不存在则创建
if not os.path.exists('project'):
    import os
    os.system('python -m venv project')

    # 读取project.json，若不存在则创建
    if not os.path.exists('project.json'):
        with open('project.json', 'w') as f:
            f.write(json.dumps([{'title': 'project', 'path': absolute_path}]))
    else:
        # 读取project.json
        with open('project.json', 'r') as f:
            data = json.load(f)
            # 检查是否已经存在
            for item in data:
                if item['path'] == absolute_path:
                    break
            else: # 不存在则添加
                data.append({'title': 'project', 'path': absolute_path})

        # 写入
        with open('project.json', 'w') as f:
            f.write(json.dumps(data))


# 定义一个路由，当访问根目录时，返回editor.html模板
@app.route('/')
def index():
    # 如果 Cookie 不存在或为空，设置一个默认值
    if not request.cookies.get('currentProjectPath'):
        # 创建一个响应对象
        response = make_response(render_template('index.html'))
        # 设置 Cookie
        response.set_cookie('currentProjectPath', value=absolute_path, max_age=3600*24*7)
        return response
    return render_template('index.html')


@app.route('/docs/<path:path>')
def docs(path):
    return render_template('public/docs/'+ path)

# dist/下的路径全部自动返回
@app.route('/<path:path>')
def static_proxy(path):
    print(path)
    return app.send_static_file("dist/"+path)

# api
@app.route('/api/<api>', methods=['GET', 'POST'])
def api(api):
    if not request.cookies.get('currentProjectPath'):
        # 创建一个响应对象
        response = make_response(render_template('index.html'))
        # 设置 Cookie
        response.set_cookie('currentProjectPath', value=absolute_path, max_age=3600*24*7)
        return response
    if api == 'pipList':
        # 获取pip列表，调用cmd命令，进入project虚拟环境，获取内容，
        current_project_path = request.cookies.get('currentProjectPath', absolute_path)
        result = pipList.main(current_project_path)
        return {'pipList': result}
    elif api == 'pyVenv':
        # 获取post参数name，path
        name = request.args.get('name')
        path = request.args.get('path')
        # 新建Python "project"虚拟环境
        os.system('python -m venv '+path+'\\'+name)
        return {'pyVenv': 'success'}
    elif api == 'pipInstall':
        # 从 GET 请求中读取参数
        package_name = request.args.get('packageName')
        install_source = request.args.get('installSource')

        # 读取Cookie-currentProjectPath，若无则为absolute_path
        current_project_path = request.cookies.get('currentProjectPath') or absolute_path

        # 检查参数是否为空
        if not package_name:
            return jsonify({'error': 'packageName is required'}), 400
        if not install_source:
            return jsonify({'error': 'installSource is required'}), 400

        # 打印参数值（实际开发中可以进行相应的处理）
        print(f"Package Name: {package_name}")
        print(f"Install Source: {install_source}")

        command = os.path.join(current_project_path, 'Scripts', 'activate') + r' && pip install '+package_name+' -i ' + install_source
        print(command)
        process = subprocess.Popen(
            command,
            shell=True,
            stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, encoding="cp936")
        stdout, stderr = process.communicate()

        print(stdout)
        print(stderr)

        # 检查命令是否成功执行
        if process.returncode == 0:
            return jsonify({'success': 'Package installed successfully'})
        else:
            return jsonify({'error': 'Failed to install package'}), 500
    elif api == 'project_list':
        # 读取project.json
        with open(current_executable_dir + '\project.json', 'r') as f:
            project_list = json.load(f)
        return jsonify(project_list)
    elif api == 'file_list':
        # 获取Cookie-currentProjectPath，若无则为'./project'
        current_project_path = request.cookies.get('currentProjectPath') or absolute_path
        print("current_project_path",current_project_path)
        print("absolute_path", absolute_path)
        try:
            # 获取currentProjectPath下的所有后缀为.boxy文件列表，返回字段为name, path, time
            file_list = []
            for file in os.listdir(current_project_path):
                if file.endswith('.boxy'):
                    file_path = os.path.join(current_project_path, file)
                    file_time = os.path.getmtime(file_path)
                    file_list.append({'name': file, 'path': file_path, 'time': file_time})
            file_list.sort(key=lambda x: x['time'], reverse=True)
            return jsonify(file_list)
        except Exception as e:
            return jsonify({'message':'failed','error': str(e)}), 403
    elif api == 'get_file':
        # 获取Cookie-currentFilePath
        current_file_path = request.cookies.get('currentFilePath')
        # 读取文件内容
        with open(current_file_path, 'r') as f:
            file_content = f.read()
            # 转换为base64
            file_content = base64.b64encode(file_content.encode('utf-8')).decode('utf-8')
        return jsonify({'file_content': file_content})
    elif api == 'save_file':
        data = request.json  # 获取 JSON 数据
        path = data.get('path')
        content = data.get('content')
        code = data.get('code')

        # base64解码转换为utf-8
        file_content = base64.b64decode(content).decode('utf-8')
        code = base64.b64decode(code).decode('utf-8')
        try:
            # 写入文件
            with open(path, 'w') as f:
                f.write(file_content)
            with open(path.replace('.boxy', '.py'), 'w') as f:
                f.write(code)
            return jsonify({'message': 'success'})
        except Exception as e:
            return jsonify({'success': False, 'error': str(e)}), 500
    elif api == 'get_absolute_path':
        name = request.args.get('name')
        current_project_path = request.cookies.get('currentProjectPath', absolute_path)
        return  jsonify({'absolute_path': os.path.join(current_project_path, name)})
    elif api == 'save_project':
        # 获取post参数name，path
        data = request.json  # 获取 JSON 数据
        name = data.get('title')
        path = data.get('path')

        exist = False
        with open(current_executable_dir + '\project.json', 'r') as f:
            dataJson = json.load(f)
            # 检查是否已经存在
            for item in dataJson:
                if item['path'] == path:
                    exist = True
                    break
            # 不存在则添加
            # 新建Python 虚拟环境
            if not exist:
                print("不存在")
                os.system('python -m venv ' + path)
                dataJson.append({'title': name, 'path': path})

        # 写入
        with open(current_executable_dir + '\project.json', 'w') as j:
            j.write(json.dumps(dataJson))

        return {'message': 'success'}
    elif api == 'delete_project':
        # 获取post参数path
        data = request.json  # 获取 JSON 数据
        current_project_path = data.get('path')
        try:
            # 删除当前项目
            shutil.rmtree(current_project_path)
            return {'message': 'success'}
        except Exception as e:
            return {'message': 'error', 'error': str(e)}
    elif api == 'delete_file':
        # 处理文件删除请求
        # 从 Cookie 中获取当前文件路径
        current_file_path = request.cookies.get('currentFilePath')
        try:
            # 删除指定路径的文件
            os.remove(current_file_path)
            return {'message': 'success'}
        except Exception as e:
            # 返回删除失败的异常信息
            return {'message': 'error', 'error': str(e)}
    elif api == 'run':
        # 获取Cookie-currentFilePath
        current_file_path = request.cookies.get('currentFilePath', None)
        if current_file_path is None:
            return jsonify({'message': 'error', 'error': 'currentFilePath is None'})
        else:
            # 获取文件名
            file_name = os.path.basename(current_file_path)
            # 获取文件名前缀
            file_prefix = os.path.splitext(file_name)[0]
            # 获取文件所在目录
            file_dir = os.path.dirname(current_file_path)
            # 获取文件所在目录的绝对路径
            file_dir_absolute = os.path.abspath(file_dir)
            # 获取对应的py文件路径
            py_file_path = os.path.join(file_dir, file_prefix + '.py')
            # 获取对应的py文件路径的绝对路径
            py_file_path_absolute = os.path.abspath(py_file_path)
            # 读取Cookie-currentProjectPath，若无则为absolute_path
            current_project_path = request.cookies.get('currentProjectPath') or absolute_path

            # 运行Py
            try:
                # 唤起cmd窗口
                # 进入项目虚拟环境
                #os.system(r'start cmd.exe /k "F:\program\StarBit\code\block-py\project\Scripts\activate && cd /d F:\program\StarBit\code\block-py\project && python test.py"')
                #os.system(r'start cmd.exe /k '+os.path.join(current_project_path, 'Scripts', 'activate') + ' && cd /d ' + file_dir_absolute + ' && python ' + file_prefix + '.py')
                #os.system('start cmd.exe /k '+os.path.join(current_project_path, 'Scripts', 'activate') + ' && cd ' + file_dir_absolute + ' && python ' + file_prefix + '.py')

                # 构造激活虚拟环境的命令
                activate_cmd = os.path.join(current_project_path, 'Scripts', 'activate')

                # 构造完整的命令字符串
                cmd_command = f'start cmd.exe /k "call {activate_cmd} && cd /d {file_dir_absolute} && python {py_file_path_absolute}"'

                # 执行命令
                os.system(cmd_command)
                return jsonify({'message': 'success'})
            except Exception as e:
                return jsonify({'message': 'error', 'error': str(e)})


if __name__ == '__main__':
    app.run(debug=True)
